package com.fxu.framework.core.base;

import cn.hutool.core.bean.copier.CopyOptions;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fxu.framework.biz.util.ErrorUtil;
import com.fxu.framework.core.enums.BaseEnum;
import com.fxu.framework.core.util.BeanUtil;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 响应数据
 * @author fangxu
 * @version 1.0.0
 */
@Data
public class Result<T> implements Serializable {
	private static final long serialVersionUID = -8496037095212798486L;

	@ApiModelProperty(value="响应状态[200正常]")
	private int code;

	@ApiModelProperty(value="接口错误信息")
	private String msg;

	@ApiModelProperty(value="返回的数据")
	private T data;

	@ApiModelProperty(value="当前第几页")
	private Long pageNum;

	@ApiModelProperty(value="页面大小")
	private Long pageSize;

	@ApiModelProperty(value="总页数")
	private Long pages;

	@ApiModelProperty(value="总数")
	private Long total;

	@ApiModelProperty(value="自增ID/UUID字段名")
	private String idName;

	/**
	 * 获取数据，返回指定的类型 (强制类型转换)
	 * @param <T> 指定返回数据的范型类型
	 * @return T 返回指定类型数据
	 */
	@JsonIgnore
	public <T> T getCaseData() {
		return data == null ? null : (T) data;
	}

	/**
	 * 获取数据集合((强制类型转换或者BeanUtil.mapToBean)(map : clazz)
	 * @param <E> 实体对象范型类型
	 * @param clazz 类型
	 * @return 实体类型对象集合
	 */
	@JsonIgnore
	@SuppressWarnings("unchecked")
	public <E> List<E> getBeanList(Class<E> clazz) {
		if (data == null) {
			return null;
		}
		List<?> dataList = (List<?>) data;
		if (dataList.size() > 0 && dataList.get(0) != null && (dataList.get(0) instanceof Map)) {
			List<E> list = new ArrayList<>();
			for (Map<?, ?> map : (List<Map<?, ?>>) data) {
				list.add(BeanUtil.toBean(map, clazz, CopyOptions.create()));
			}
			return list;
		}
		return (List<E>) data;
	}

	/**
	 * 获取数据集合(强制类型转换或者BeanUtil.beanListToMap)
	 * @return Map 数据 集合
	 */
	@JsonIgnore
	@SuppressWarnings("unchecked")
	public List<Map<String, Object>> getMapList() {
		if (data == null) {
			return null;
		}
		List<?> list = (List<?>) data;
		if (list.size() <= 0 || list.get(0) == null) {
			return (List<Map<String, Object>>) list;
		}
		if (list.get(0) instanceof Map) {
			return (List<Map<String, Object>>) list;
		} else {
			return BeanUtil.beanListToMap(list);
		}
	}

	/**
	 * 获取数据(BeanUtil.mapToBean)(map : clazz)
	 * @param clazz 类型
	 * @param <E> clazz范型
	 * @return E数据对象
	 */
	@JsonIgnore
	@SuppressWarnings("unchecked")
	public <E> E getBeanData(Class<E> clazz) {
		if (data == null) {
			return null;
		}
		if (data instanceof Map) {
			return BeanUtil.toBean(data, clazz, CopyOptions.create());
		} else {
			return (E) data;
		}
	}

	/**
	 * 获取数据 (强制类型转换或者BeanUtil.mapToBean)
	 * @return Map数据对象
	 */
	@JsonIgnore
	@SuppressWarnings("unchecked")
	public Map<String, Object> getMapData() {
		if (data == null) {
			return null;
		}
		if (data instanceof Map) {
			return (Map<String, Object>) data;
		} else {
			return BeanUtil.beanToMap(data);
		}
	}

	public Result<T> data(T data) {
		this.data = data;
		return this;
	}

	@JsonIgnore
	public boolean isSuccess() {
		return code == ResultCode.SUCCESS.code();
	}

	@JsonIgnore
	public boolean isError() {
		return code != ResultCode.SUCCESS.code();
	}

	/*public static <T> Result<T> ok() {
		Result<T> result = new Result<>();
		result.code = ResultCode.SUCCESS.code();
		return result;
	}*/

	public static <T> Result<T> ok(T data) {
		Result<T> result = new Result<>();
		result.code = ResultCode.SUCCESS.code();
		result.data = data;
		return result;
	}

	public static <T> Result<T> ok(T data, Long count, String idName) {
		Result<T> result = new Result<>();
		result.code = ResultCode.SUCCESS.code();
		result.data = data;
		result.total = count;
		result.idName = idName;
		return result;
	}

	public static <T> Result<List<T>> ok(IPage<T> page) {
		Result<List<T>> result = new Result<>();
		if (page == null) {
			result.code = ResultCode.ERROR.code();
			result.msg = "出现错误!";
			return result;
		}
		result.code = ResultCode.SUCCESS.code();
		result.data = page.getRecords();
		result.pageNum = page.getCurrent();
		result.pageSize = page.getSize();
		result.pages = page.getPages();
		result.total = page.getTotal();
		return result;
	}

	public static <T> Result<T> ok(IPage<?> page, T data) {
		Result<T> result = new Result<>();
		if (page == null) {
			result.code = ResultCode.ERROR.code();
			result.msg = "出现错误!";
			return result;
		}
		result.code = ResultCode.SUCCESS.code();
		result.data = data;
		result.pageNum = page.getCurrent();
		result.pageSize = page.getSize();
		result.pages = page.getPages();
		result.total = page.getTotal();
		return result;
	}

	public static <T> Result<List<T>> ok(IPage<?> page, List<T> data) {
		Result<List<T>> result = new Result<>();
		if (page == null) {
			result.code = ResultCode.ERROR.code();
			result.msg = "出现错误!";
			return result;
		}
		result.code = ResultCode.SUCCESS.code();
		result.data = data;
		result.pageNum = page.getCurrent();
		result.pageSize = page.getSize();
		result.pages = page.getPages();
		result.total = page.getTotal();
		return result;
	}

	public static <T> Result<T> error(String error) {
		return error(ResultCode.ERROR.code(), error);
	}

	public static <T> Result<T> error(int code, String error) {
		Result<T> result = new Result<>();
		result.code = code;
		result.msg = ErrorUtil.getErrorMsg(error);
		return result;
	}

	public static <T> Result<T> error(String format, Object ... args) {
		return error(ResultCode.ERROR.code(), String.format(format, args));
	}

	public static <T> Result<T> error(BaseEnum<Integer, String> baseEnum) {
		return error(baseEnum.code(), baseEnum.desc());
	}
}